﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;
using indigo;
using System.IO;
using System.Drawing.Imaging;
using System.Drawing;

namespace dingonettest
{  
   class Program
   {                                                        
      public class GDI
      {
         [System.Runtime.InteropServices.DllImport("gdi32.dll")]
         internal static extern bool Rectangle(
            IntPtr hdc,
            int ulCornerX, int ulCornerY,
            int lrCornerX, int lrCornerY);
      }
                                      
      const String MOLPATH = "../../../../../data/molfiles/";
      const String RXNPATH = "../../../../../data/rxn/";

      [System.Runtime.InteropServices.DllImport("gdi32")]
      public static extern int GetEnhMetaFileBits(IntPtr hemf, int cbBuffer, byte[] lpbBuffer);

      static void SaveMetafile(Metafile mf, String path)
      {
         IntPtr henh = mf.GetHenhmetafile();
         int size = GetEnhMetaFileBits(henh, 0, null);

         byte[] buffer = new byte[size];

         if (GetEnhMetaFileBits(henh, size, buffer) <= 0)
            throw new SystemException("GetEnhMetaFileBits");

         FileStream fs = new FileStream(path, FileMode.OpenOrCreate);

         fs.Write(buffer, 0, buffer.Count());
      }

      static unsafe void TestDingo ()
      {         
         Dingo dingo = new Dingo();
         try
         {
            //string[] files = Directory.GetFiles(MOLPATH, "*.mol");
            //dingo.setLogPath(Path.Combine(MOLPATH, "dingo.log"));
            //dingo.loadMoleculeFromFile(files[5]); 

            Console.WriteLine(Dingo.versionRevisionString());
            Console.WriteLine(Dingo.versionCode());
            dingo.loadMolecule("CCN(CC)C(=O)[C@H]1CN([C@@H]2CC3=CNC4=CC=CC(=C34)C2=C1)C");
            dingo.setOptions("aromatization=aromatize; output-file=out.png;");
            dingo.setOption("output-format", "png");
            dingo.render();
            dingo.reset();

            //dingo.loadMoleculeFromFile(MOLPATH + "complex_arom.mol");
            //dingo.setOutputFile("test.png");
            //dingo.setOutputFormat("png");
            //dingo.render();
            //foreach (string file in files)
            //{           
            //   dingo.loadMoleculeFromFile(file);
            //   dingo.setOutputFile(Path.Combine(MOLPATH, Path.GetFileNameWithoutExtension(file) + ".png"));
            //   dingo.setOutputFormat("png");
            //   dingo.setBondLength(90);
            //   dingo.setMarginFactor(0.55f);
            //   dingo.render();
            //}             
            dingo.reset();
         }
         catch (DingoException ex) 
         {
            Console.WriteLine(ex.Message);
         }
         dingo = null;
      }

      public static byte[] GetSmileImage()
      {
         int w = 1000, h = 1000;
         var format = ImageFormat.Png;
         Bitmap bmp;
         using (var dng = new Dingo())
         {
            dng.loadMolecule("O=C(N(CS)CC)[C@@H]1CN([C@@H]2CC3=CNC4=CC=CC(=C34)C2=C1)Cl");
            dng.setOptions("coloring=1; highlight-thickness-enabled=1; relative-thickness=1.0");
            if (format == ImageFormat.Png)
               bmp = dng.renderToBitmap(w, h);
            else
               bmp = dng.renderToBitmap(w, h, Color.White);
            dng.reset();
         }
         using (MemoryStream mem = new MemoryStream())
         {
            bmp.Save(mem, format);
            return mem.ToArray();
         }
      }
      public static byte[] GetSmileImage1()
      {
         int w = 1000, h = 1000;
         var format = ImageFormat.Jpeg;
         byte[] bb;
         using (var dng = new Dingo())
         {
            dng.loadMolecule("O=C(N(CS)CC)[C@@H]1CN([C@@H]2CC3=CNC4=CC=CC(=C34)C2=C1)Cl");
            dng.setOptions("coloring=1; highlight-thickness-enabled=1; output-format=png");
            if (format != ImageFormat.Png)
               dng.setOptions("background-color=1.0,1.0,1.0");
            dng.setImageSize(w, h);
            dng.render();
            bb = dng.getResult();
            dng.reset();
         }
         if (format == ImageFormat.Png)
            return bb;
         Image img = null;
         using (MemoryStream ms = new MemoryStream(bb))
         {
            img = Image.FromStream(ms);
         }
         using (MemoryStream mem = new MemoryStream())
         {
            img.Save(mem, format);
            return mem.ToArray();
         }
      }

      static HashSet<int> smap = new HashSet<int>();

      static void runConc(object o)
      {
         string fmt = "png";
         int id = (int)o;
         Dingo d = new Dingo();
         for (int i = 0; i < 40; ++i)
         {
            try
            {
               d.loadMolecule("O=C(N(CS)CC)[C@@H]1CN([C@@H]2CC3=CNC4=CC=CC(=C34)C2=C1)Cl");
               d.setOption("output-format", fmt);
               d.setOption("bond-length", 30);
               d.render();
               byte[] bb = d.getResult();
               int len = bb.Length;
               bool save = false;
               lock (smap)
               {
                  if (!smap.Contains(len))
                  {
                     save = true;
                     smap.Add(len);
                  }
               }

               Console.WriteLine(id + ": " + len);
               if (save)
               {
                  FileStream fs = new FileStream(fmt + "/t" + len + "." + fmt, FileMode.Create);
                  fs.Write(bb, 0, len);
               }
               d.reset();
            }
            catch (DingoException dex)
            {
               Console.WriteLine(dex.Message);
               Console.WriteLine(dex.StackTrace);
            }
         }  
      }

      static void TestConcurrent ()
      {
         int num = 4;
         Thread[] tt = new Thread[num];
         for (int i = 0; i < num; ++i)
            tt[i] = new Thread(new ParameterizedThreadStart(runConc));
         for (int i = 0; i < num; ++i)
            tt[i].Start(i);
         Console.WriteLine("Press <Return> to continue");
         Console.ReadLine();
      }

      static void Main(string[] args)
      {
         try
         {
            TestConcurrent();
            //byte[] bb = GetSmileImage1();
            //FileStream fs = new FileStream("ms.jpg", FileMode.Create);
            //fs.Write(bb, 0, bb.Length);
            //fs.Close();
            //TestDingo();

            Console.WriteLine("Success");
         }
         catch (Exception ex)
         {
            Console.WriteLine("Exception:\n\t" + ex.Message);
         }
         Console.WriteLine("Press <Return> to continue");
         Console.ReadLine();
      }
   }
}
